﻿using System;
using System.Web;
using System.Web.Caching;
using Microsoft.SharePoint;

namespace Eneta.Portal.Common.Repository
{
    /// <summary>
    /// Class for base repository. All repositories are inherited from this class. This class provides 
    /// also common querying methods for extended repositories.
    /// </summary>
    public abstract class BaseRepository
    {
        /// <summary>
        /// Gets or sets the site id.
        /// </summary>
        public Guid SiteId { get; protected set;}

        /// <summary>
        /// Gets or sets the web id.
        /// </summary>
        public Guid WebId  { get; protected set;}

        /// <summary>
        /// Initializes a new instance of the <see cref="BaseRepository"/> class.
        /// </summary>
        protected BaseRepository(SPWeb web)
        {
            SiteId = web.Site.ID;
            WebId = web.ID;
        }

        /// <summary>
        /// Queries the list for item by given field value.
        /// </summary>
        /// <param name="list">The list to query.</param>
        /// <param name="fieldName">Name of the field.</param>
        /// <param name="fieldValue">The field value.</param>
        protected SPListItem QueryItemByFieldValue(SPList list, string fieldName, string fieldValue)
        {
            var items = QueryItemsByFieldValue(list, fieldName, fieldValue, 1);
            if (items == null)
                return null;
            if (items.Count == 0)
                return null;
            return items[0];
        }

        protected SPListItemCollection QueryItemsByFieldValue(SPList list, string fieldName, string fieldValue)
        {
            return QueryItemsByFieldValue(list, fieldName, fieldValue, 0);
        }
        protected SPListItemCollection QueryItemsByFieldValue(SPList list, string fieldName, string fieldValue, int limit)
        {
            return QueryItemsByFieldValue(list, fieldName, fieldValue, string.Empty, false, 0);
        }
        protected SPListItemCollection QueryItemsByFieldValue(SPList list, string fieldName, string fieldValue, string orderBy, bool ascending, int limit)
        {
            var fieldType = list.Fields[fieldName].TypeAsString;
            var queryString = "<Where><Eq><FieldRef Name='{0}'/><Value Type='{1}'>{2}</Value></Eq></Where>";
            if(!string.IsNullOrEmpty(orderBy))
            {
                queryString += "<OrderBy><FieldRef Name='" + orderBy + "' Ascending='";
                if (ascending)
                    queryString += "True";
                else
                    queryString += "False";
                queryString += "' /></OrderBy>";
            }
            queryString = string.Format(queryString, fieldName, fieldType, fieldValue);

            return ExecuteQuery(list, queryString, limit);
        }

        protected SPListItemCollection ExecuteQuery(SPList list, string queryString)
        {
            return ExecuteQuery(list, queryString, 0);
        }
        protected SPListItemCollection ExecuteQuery(SPList list, string queryString, int limit)
        {
            //Logger.LogInfo("ExecuteQuery(): List : " + list.Title,GetType().ToString());
            //Logger.LogInfo("ExecuteQuery(): Query: " + queryString, GetType().ToString());

            try
            {
                var query = new SPQuery
                                {
                                    Query = queryString
                                };

                if (limit > 0)
                    query.RowLimit = (uint)limit;

                var items = list.GetItems(query);
                //Logger.LogInfo("ExecuteQuery(): Results: " + items.Count, GetType().ToString());

                return items;
            }
            catch(Exception ex)
            {
                Logger.LogException(ex);
                throw;
            }
        }

        protected SPListItemCollection GetPendingItems(SPList list, string contentType, string order, bool ascending)
        {
            return GetItemsByModerationStatus(list, Resources.ModerationStatusPending, contentType, order, ascending);
        }

        protected SPListItemCollection GetApprovedItems(SPList list, string contentType, string order, bool ascending)
        {
            return GetItemsByModerationStatus(list, Resources.ModerationStatusApproved, contentType, order, ascending);            
        }

        protected SPListItemCollection GetApprovedItems(SPList list, string order, bool ascending)
        {
            return GetItemsByModerationStatus(list, Resources.ModerationStatusApproved, order, ascending);
        }

        protected string GetRssHeader(string title, string link)
        {
            var header = @"
                    <rss 
	                    xmlns:content=""http://purl.org/rss/1.0/modules/content/"" 
	                    xmlns:wfw=""http://wellformedweb.org/CommentAPI/"" 
	                    xmlns:dc=""http://purl.org/dc/elements/1.1/"" 
	                    xmlns:atom=""http://www.w3.org/2005/Atom"" 
	                    xmlns:sy=""http://purl.org/rss/1.0/modules/syndication/"" 
	                    xmlns:slash=""http://purl.org/rss/1.0/modules/slash/"" 
	                    version=""2.0"">
	                    <channel>
		                    <title>{0}</title>
		                    <link>{1}</link>
		                    <description></description>
		                    <lastBuildDate>{2}</lastBuildDate>
		                    <generator>Eneta portaal</generator>
		                    <language>et</language>
		                    <sy:updatePeriod>hourly</sy:updatePeriod>
		                    <sy:updateFrequency>1</sy:updateFrequency>
                ";
            //<atom10:link 
            //    xmlns:atom10=""http://www.w3.org/2005/Atom"" 
            //    rel=""self"" 
            //    href=""http://feeds.feedburner.com/wekeroad/EeKc"" 
            //    type=""application/rss+xml"" />
            header = string.Format(header, title, link, DateTime.Now.ToString("r"));

            return header;
        }

        protected string GetRssFooter()
        {
            return "</channel></rss>";
        }

        private SPListItemCollection GetItemsByModerationStatus(SPList list, string status, string orderBy, bool ascending)
        {
            string query = "<Where>";
            query += "<Eq><FieldRef Name='_ModerationStatus'/><Value Type='ModStat'>{0}</Value></Eq>";
            query += "</Where>";
            query = string.Format(query, status);

            if (!string.IsNullOrEmpty(orderBy))
            {
                query += "<OrderBy><FieldRef Name='" + orderBy + "' ";
                if (!ascending)
                    query += "Ascending='False'";
                query += "/></OrderBy>";
            }

            return ExecuteQuery(list, query);
        }

        private SPListItemCollection GetItemsByModerationStatus(SPList list, string status, string contentType, string orderBy, bool ascending)
        {
            string query = "<Where><And>";
            query += "<Eq><FieldRef Name='_ModerationStatus'/><Value Type='ModStat'>{0}</Value></Eq>";
            query += "<Eq><FieldRef Name='ContentType'/><Value Type='Text'>{1}</Value></Eq>";
            query += "</And></Where>";
            query = string.Format(query, status, contentType);

            if (!string.IsNullOrEmpty(orderBy))
            {
                query += "<OrderBy><FieldRef Name='" + orderBy + "' ";
                if (!ascending)
                    query += "Ascending='False'";
                query += "/></OrderBy>";
            }

            return ExecuteQuery(list, query);
        }

        protected SPListItem GetPreviuosItemById(SPList list, int itemId)
        {
            throw new NotImplementedException();
        }

        protected SPListItem GetNextItemById(SPList list, int itemId)
        {
            throw new NotImplementedException();
        }

        #region Caching
        protected T GetFromCache<T>(string cacheKey) where T : class
        {
            var context = HttpContext.Current;

            if (context == null)
                return null;
            if (context.Cache[cacheKey] == null)
                return null;

            return context.Cache[cacheKey] as T;
        }

        protected void SaveToCache(string cacheKey, object o)
        {
            SaveToCache(cacheKey, o, 0);
        }

        protected void SaveToCache(string cacheKey, object o, int timeToLive)
        {
            if (HttpContext.Current == null)
                return;
            var cache = HttpContext.Current.Cache;
            if (o == null)
            {
                cache.Remove(cacheKey);
                return;
            }

            if (timeToLive <= 0)
            {
                cache.Insert(cacheKey, o);
                return;
            }
            cache.Insert(cacheKey, o,null, DateTime.UtcNow.AddSeconds(timeToLive), Cache.NoSlidingExpiration);
        }
        #endregion

        protected string GenerateUniquePageName(SPList listItem)
        {
            if (listItem == null)
                return null;

            throw new NotImplementedException();
        }
    }
}